package com.njcb.ams.support.beanprocessor;

import com.njcb.ams.pojo.bo.DataDicConfig;
import com.njcb.ams.support.annotation.AmsConfig;
import com.njcb.ams.support.annotation.DataDic;
import com.njcb.ams.support.config.AmsConfigUtil;
import com.njcb.ams.support.exception.ExceptionUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.filter.AnnotationTypeFilter;

import java.lang.reflect.Method;
import java.util.Map;
import java.util.Set;

/**
 * 自定义注解扫描器
 * 扫描自定义注解
 *
 * @author liuyanlong
 */
public final class AmsBusinessBeanScanner extends ClassPathBeanDefinitionScanner {
    private static final Logger logger = LoggerFactory.getLogger(AmsBusinessBeanScanner.class);

    private BeanDefinitionRegistry defaultRegistry;

    public AmsBusinessBeanScanner(BeanDefinitionRegistry defaultRegistry, BeanDefinitionRegistry customRegistry) {
        super(customRegistry, false);
        this.defaultRegistry = defaultRegistry;
    }

    @Override
    public Set<BeanDefinitionHolder> doScan(String... basePackages) {
        //添加过滤条件
        addIncludeFilter(new AnnotationTypeFilter(AmsConfig.class));
        addIncludeFilter(new AnnotationTypeFilter(DataDic.class));
        Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);
        for (BeanDefinitionHolder holder : beanDefinitions) {
            ScannedGenericBeanDefinition definition = (ScannedGenericBeanDefinition) holder.getBeanDefinition();
            if (defaultRegistry.containsBeanDefinition(holder.getBeanName())) {
                BeanDefinition orgBeanDefinition = defaultRegistry.getBeanDefinition(holder.getBeanName());
                logger.debug("自定义扫描到:" + orgBeanDefinition);
            }
            AnnotationMetadata meta = definition.getMetadata();
            Boolean isAmsConfig = meta.hasAnnotation(AmsConfig.class.getName());
            Boolean isDataDic = meta.hasAnnotation(DataDic.class.getName());
            if (isDataDic) {
                dataDicExecute(meta);
            }
            if (isAmsConfig) {
                //TODO 有误用
                amsConfigExecute(meta);
            } else {
                /**
                 * 暂不会执行到此地方
                 * 生成对象增强代理类
                 */
                definition.getPropertyValues().add("innerClassName", meta.getClassName());
                definition.setBeanClass(AmsBusinessBeanFactory.class);
            }
        }
        return beanDefinitions;
    }

    private void dataDicExecute(AnnotationMetadata meta) {
        try {
            Map<String, Object> annotationMap = meta.getAnnotationAttributes(DataDic.class.getName());
            Class<?> dataDicClazz = Class.forName(meta.getClassName());
            if (dataDicClazz.isEnum()) {
                Class<Enum> clazz = (Class<Enum>) Class.forName(dataDicClazz.getName());
                Enum[] enumConstants = clazz.getEnumConstants();
                Method getCode = clazz.getMethod("getCode");
                Method getDesc = clazz.getMethod("getDesc");
                for (Enum enumField : enumConstants) {
                    String code = getCode.invoke(enumField).toString();
                    String desc = getDesc.invoke(enumField).toString();
                    String dataType = annotationMap.get("dataType").toString();
                    String dataTypeName = annotationMap.get("dataTypeName").toString();
                    DataDicConfig dataDicConfig = new DataDicConfig(code, desc, dataType, dataTypeName);
                    AmsConfigUtil.addAmsDataDic(dataType, dataDicConfig);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            ExceptionUtil.throwAppException("字典枚举类错误，请检查[" + meta.getClassName() + "]");
        }
    }

    @Override
    public boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
        return super.isCandidateComponent(beanDefinition);
    }

    /**
     * 处理配置类
     *
     * @param meta
     */
    private void amsConfigExecute(AnnotationMetadata meta) {
        String[] interfaces = meta.getInterfaceNames();
        Object bean = null;
        try {
            bean = Class.forName(meta.getClassName()).newInstance();
        } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
            e.printStackTrace();
        }
        if (!Object.class.getName().equals(meta.getSuperClassName())) {
            AmsConfigUtil.addBean(meta.getSuperClassName(), bean);
        }
        for (String interfaceName : interfaces) {
            AmsConfigUtil.addBean(interfaceName, bean);
        }
    }

}
